import { debounce } from 'lodash';
import priorityWorkerManager from './priorityWorkerManager';

/**
 * 懒加载器类，用于管理画布上对象的按需加载
 * 通过视口和预加载区域来优化性能，减少内存占用
 */
class AdvancedLazyLoader {
    constructor(canvas, objects = [], options = {}) {
        this.canvas = canvas;
        this.objects = new Set(objects);
        this.options = {
            viewportMargin: options.viewportMargin || 200,
            preloadMargin: options.preloadMargin || 300,
            batchSize: options.batchSize || 10,
            ...options
        };

        // 已加载的对象集合，记录已经添加到画布的对象
        this.loadedObjects = new Set();

        // 视口内的对象集合，记录当前在视口范围内可见的对象
        this.viewportObjects = new Set();

        // 预加载的对象集合，记录即将进入视口的对象
        this.preloadObjects = new Set();

        // 优先级队列，用于按优先级顺序加载对象
        this.priorityQueue = [];

        // 加载状态标志，防止重复加载
        this.isLoading = false;

        // 保存状态标志，在保存过程中防止对象被卸载
        this.isSaving = false;

        console.log('LazyLoader initialized with:', {
            totalObjects: this.objects.size,
            viewportMargin: this.options.viewportMargin,
            preloadMargin: this.options.preloadMargin,
            batchSize: this.options.batchSize
        });

        // 绑定事件处理函数
        this.handleViewportChange = debounce(this.handleViewportChange.bind(this), 100);
        this.handleObjectAdded = this.handleObjectAdded.bind(this);
        this.handleObjectRemoved = this.handleObjectRemoved.bind(this);

        // 添加事件监听
        this.canvas.on('after:render', this.handleViewportChange);
        this.canvas.on('object:added', this.handleObjectAdded);
        this.canvas.on('object:removed', this.handleObjectRemoved);

        // 初始加载
        this.handleViewportChange();
    }

    /**
     * 处理视口变化事件
     * 当画布视口发生变化时，更新视口对象和预加载区域
     */
    async handleViewportChange() {
        // 获取当前视口边界
        const viewport = this.getViewportBounds();
        // 获取预加载区域
        const preloadArea = this.getPreloadArea(viewport);

        // 更新视口对象
        await this.updateViewportObjects(viewport);

        // 预加载对象
        await this.preloadObjectsInArea(preloadArea);

        // 更新优先级   
        this.updatePriorities();
    }

    /**
     * 处理对象添加事件
     * 当新对象添加到画布时，将其标记为已加载
     */
    handleObjectAdded(e) {
        const object = e.target;
        if (!this.loadedObjects.has(object)) {
            this.loadedObjects.add(object);
        }
    }

    /**
     * 处理对象移除事件
     * 当对象从画布移除时，清理相关状态
     */
    handleObjectRemoved(e) {
        const object = e.target;
        this.loadedObjects.delete(object);
        this.viewportObjects.delete(object);
        this.preloadObjects.delete(object);
    }

    /**
     * 获取当前视口边界
     */
    getViewportBounds() {
        // 获取当前画布的视口变换矩阵
        //[
        //    2, 0, 
        //    0, 2, 
        //    -100, -50,
        //]
        // 画布在水平方向上放大了 2 倍（scale_x = 2）。
        // 画布在垂直方向上放大了 2 倍（scale_y = 2）。
        // 画布在水平方向上向左平移了 100 个单位（translate_x = -100）。
        // 画布在垂直方向上向上平移了 50 个单位（translate_y = -50）
        const vpt = this.canvas.viewportTransform;
        const width = this.canvas.width;
        const height = this.canvas.height;

        return {
            left: -vpt[4] / vpt[0],
            top: -vpt[5] / vpt[3],
            right: (-vpt[4] + width) / vpt[0],
            bottom: (-vpt[5] + height) / vpt[3]
        };
    }

    /**
     * 获取预加载区域
     * 基于当前视口和预加载边距计算预加载区域
     */
    getPreloadArea(viewport) {
        const margin = this.options.preloadMargin;
        return {
            left: viewport.left - margin,
            top: viewport.top - margin,
            right: viewport.right + margin,
            bottom: viewport.bottom + margin
        };
    }

    /**
     * 更新视口对象
     * 根据当前视口更新需要显示的对象
     */
    async updateViewportObjects(viewport) {
        const newViewportObjects = new Set();
        const margin = this.options.viewportMargin;

        this.objects.forEach((object) => {
            // 获取对象的边界矩形
            const bounds = object.getBoundingRect();
            // 检查对象是否在视口内
            if (this.isInViewport(bounds, viewport, margin)) {
                // 将对象添加到视口对象集合
                newViewportObjects.add(object);
                // 如果对象未加载，则加载对象
                if (!this.loadedObjects.has(object)) {
                    this.loadObject(object);
                }
            }
        });

        // 清理不再在视口中的对象
        this.viewportObjects.forEach((object) => {
            if (!newViewportObjects.has(object)) {
                this.unloadObject(object);
            }
        });

        this.viewportObjects = newViewportObjects;
    }

    /**
     * 预加载区域内的对象
     * 加载即将进入视口的对象，提高用户体验
     */
    async preloadObjectsInArea(area) {
        const batch = [];
        this.objects.forEach((object) => {
            if (!this.loadedObjects.has(object) && !this.viewportObjects.has(object)) {
                const bounds = object.getBoundingRect();
                if (this.isInViewport(bounds, area, 0)) {
                    batch.push(object);
                    if (batch.length >= this.options.batchSize) {
                        this.loadObjects(batch);
                        batch.length = 0;
                    }
                }
            }
        });

        if (batch.length > 0) {
            this.loadObjects(batch);
        }
    }

    /**
     * 检查对象是否在视口内
     */
    isInViewport(bounds, viewport, margin) {
        return !(
            bounds.left > viewport.right + margin ||
            bounds.right < viewport.left - margin ||
            bounds.top > viewport.bottom + margin ||
            bounds.bottom < viewport.top - margin
        );
    }

    /**
     * 加载单个对象
     * 将对象添加到画布并标记为已加载
     */
    loadObject(object) {
        if (!object.loaded) {
            object.loaded = true;
            if (!this.canvas.contains(object)) {
                this.canvas.add(object);
            }
            this.loadedObjects.add(object);
        }
    }

    /**
     * 卸载单个对象
     * 从画布移除对象并清理相关状态
     */
    unloadObject(object) {
        if (object.loaded && !this.isSaving) {
            object.loaded = false;
            this.canvas.remove(object);
            this.loadedObjects.delete(object);
        }
    }

    /**
     * 批量加载对象
     */
    loadObjects(objects) {
        objects.forEach((object) => this.loadObject(object));
    }

    /**
     * 更新对象列表
     * 当画布对象发生变化时更新管理对象
     * 撤销/重做操作
     */
    updateObjects(newObjects) {
        this.objects = new Set(newObjects);
        this.handleViewportChange();
    }

    /**
     * 获取视口中心点坐标
     */
    getViewportCenter() {
        const viewport = this.getViewportBounds();
        return {
            x: (viewport.left + viewport.right) / 2,
            y: (viewport.top + viewport.bottom) / 2
        };
    }

    /**
     * 计算对象加载优先级
     * 基于对象到视口中心的距离计算优先级
     * 距离越近，优先级越高
     */
    calculatePriority(object) {
        const viewportCenter = this.getViewportCenter();
        const objectCenter = {
            x: object.left + object.width / 2,
            y: object.top + object.height / 2
        };
        // 计算对象中心点到视口中心的距离
        const distance = Math.sqrt(
            Math.pow(objectCenter.x - viewportCenter.x, 2) +
                Math.pow(objectCenter.y - viewportCenter.y, 2)
        );

        // 距离越近，优先级越高
        const priority = 1 / (1 + distance);

        console.log(`Priority calculated for object ${object.id || 'unknown'}:`, {
            distance,
            priority,
            viewportCenter,
            objectCenter
        });

        return priority;
    }

    /**
     * 更新所有对象的优先级
     * 重新计算未加载对象的优先级并排序
     */
   async updatePriorities() {
        console.log('Updating priorities...');
        console.log('Current loaded objects:', this.loadedObjects.size);
        console.log('Current viewport objects:', this.viewportObjects.size);
        console.log('Current preload objects:', this.preloadObjects.size);

        // 过滤掉已加载的对象
        const unloadedObjects = Array.from(this.objects).filter(
            (obj) => !this.loadedObjects.has(obj)
        );

        console.log('Unloaded objects count:', unloadedObjects.length);

        // // 计算每个对象的优先级
        // this.priorityQueue = unloadedObjects.map((obj) => ({
        //     object: obj,
        //     priority: this.calculatePriority(obj)
        // }));
        const priorities = await priorityWorkerManager.calculatePriorities(
            unloadedObjects,
            this.getViewportCenter()
        );

        this.priorityQueue = priorities;
        // 按优先级排序
        // this.priorityQueue.sort((a, b) => b.priority - a.priority);

        console.log('Priority queue updated:', {
            queueLength: this.priorityQueue.length,
            topPriorities: this.priorityQueue.slice(0, 3).map((item) => ({
                id: item.object.id || 'unknown',
                priority: item.priority
            }))
        });

        // 触发下一批加载
        this.loadNextBatch();
    }

    /**
     * 加载下一批对象
     * 根据优先级队列加载指定数量的对象
     */
    async loadNextBatch() {
        if (this.isLoading || this.isSaving) {
            console.log('Loading skipped - isLoading:', this.isLoading, 'isSaving:', this.isSaving);
            return;
        }

        this.isLoading = true;
        console.log('Starting to load next batch...');

        try {
            const batch = this.priorityQueue.splice(0, this.options.batchSize);
            console.log('Processing batch:', {
                batchSize: batch.length,
                objects: batch.map((item) => item.object.id || 'unknown')
            });

            for (const { object } of batch) {
                if (!this.loadedObjects.has(object)) {
                    console.log(`Loading object ${object.id || 'unknown'}`);
                    await this.loadObject(object);
                }
            }
        } catch (error) {
            console.error('Error loading batch:', error);
        } finally {
            this.isLoading = false;
            console.log('Batch loading completed');

            // 如果还有对象需要加载，继续加载下一批
            if (this.priorityQueue.length > 0) {
                console.log('More objects to load, scheduling next batch...');
                setTimeout(() => this.loadNextBatch(), 0);
            } else {
                console.log('All objects loaded');
            }
        }
    }

    /**
     * 准备保存
     * 在保存画布前加载所有对象
     */
    prepareForSave() {
        this.isSaving = true;
        this.objects.forEach((object) => {
            this.loadObject(object);
        });
    }

    /**
     * 完成保存
     * 保存完成后恢复懒加载状态
     */
    finishSave() {
        this.isSaving = false;
        this.handleViewportChange();
    }

    /**
     * 清理资源
     * 移除事件监听并清理所有状态
     */
    dispose() {
        this.canvas.off('after:render', this.handleViewportChange);
        this.canvas.off('object:added', this.handleObjectAdded);
        this.canvas.off('object:removed', this.handleObjectRemoved);
        this.loadedObjects.clear();
        this.viewportObjects.clear();
        this.preloadObjects.clear();
        this.priorityQueue = [];
        this.isSaving = false;
    }
}

export default AdvancedLazyLoader;
